import sys
sys.path.append("..")   #也可以这样
from PIL import Image
import os
import time
import numpy as np
from external.tools import read_image
from utils.cloud_utils import main_upload_file_to_aliyun,main_upload_file_to_qiniu
import tempfile
import shutil

def cosine_similarity(vector_a, vector_b):
    return np.dot(vector_a, vector_b) / (np.linalg.norm(vector_a) * np.linalg.norm(vector_b))

def find_best_face(face_group):
    return max(face_group, key=lambda x: x['det_score'])


def crop_and_save_face_image(frame_path, face, output_folder, face_index, scale_factor=3.5):
    """
    裁剪并保存人脸图像，为每个图像生成唯一的文件名。
    scale_factor为放大系数，默认为1.5。
    """
    image = Image.open(frame_path)
    bbox = face['bbox']
    width, height = image.size

    # 计算放大后的边界框
    bbox_width = bbox[2] - bbox[0]
    bbox_height = bbox[3] - bbox[1]
    delta_width = bbox_width * (scale_factor - 1) / 2
    delta_height = bbox_height * (scale_factor - 1) / 2

    # 确保边界框不超出图像边界
    new_bbox = [
        max(bbox[0] - delta_width, 0),
        max(bbox[1] - delta_height, 0),
        min(bbox[2] + delta_width, width),
        min(bbox[3] + delta_height, height)
    ]

    cropped_image = image.crop(tuple(map(int, new_bbox)))
    face_image_name = f"best_face_{face_index}_{int(time.time())}_{os.path.basename(frame_path)}"
    face_image_path = os.path.join(output_folder, face_image_name)
    cropped_image.save(face_image_path)

    return face_image_path

def process_video_frames(face_data,output_folder, similarity_threshold=0.5):
    grouped_faces = []
    best_faces_with_path = []
    face_index = 0

    for frame_path, faces in face_data.items():
        for face in faces:
            face['frame_path'] = frame_path  # 记录人脸所在的帧路径
            # 只有当置信度大于一定的层度,才可以进行下面的分组,当置信度小于0.5的时候,这个就不认为这是一张脸
            if face['det_score'] < 0.75:   # < 0.75这个就不当做是一张脸
                continue
            found_group = False
            for group in grouped_faces:
                for existing_face in group:
                    if cosine_similarity(face['embedding'], existing_face['embedding']) > similarity_threshold:
                        group.append(face)
                        found_group = True
                        break
                if found_group:
                    break
            if not found_group:
                grouped_faces.append([face])

    for group in grouped_faces:
        best_face = find_best_face(group)  # 先对人脸进行分组,TODO: 这里要做的就是要对人脸的执行度进行过滤!
        best_face_image_path = crop_and_save_face_image(best_face['frame_path'], best_face, output_folder, face_index)
        best_faces_with_path.append({**best_face, 'image_path': best_face_image_path})
        face_index += 1

    return best_faces_with_path


def start(face_data,oss_name="ali") -> list:
    # 从视频中获取最佳的人脸,返回成list
    from config import similarity_threshold
    from config import kSourceVideosData
    # temp_dir是kSourceVideosData下的一个临时目录,唯一文件名
    with tempfile.TemporaryDirectory(dir=kSourceVideosData) as temp_dir:
        best_faces = process_video_frames(face_data,temp_dir, similarity_threshold=similarity_threshold)  # TODO: 需要做成可以单独判断的,多人视频换脸中的人脸,需要降低相似度,可以把人脸的置信度较低的看下
        face_image_urls = []
        for base_face in best_faces:
            if oss_name == "qiniu":
                url_path = main_upload_file_to_qiniu(base_face["image_path"])
            else:            
                url_path = main_upload_file_to_aliyun(base_face["image_path"])  # 转成线上的地址,返回到线上路径
            face_image_urls.append(url_path)
    return face_image_urls



import os
import threading
import tempfile
# 多线程下载图片
def process_image(image_path, face_detection_function, face_data, max_faces_per_frame=8):
    target_image = read_image(image_path)
    video_frames = face_detection_function(target_image, max_num=max_faces_per_frame)
    face_data[image_path] = video_frames


from loguru import logger   
# 分析所有的人脸到数据中
def process_all_frames_in_folder(folder_path, face_detection_function, max_faces_per_frame=8):
    face_data = {}
    threads = []
    # logger.debug(os.listdir(folder_path))
    for filename in os.listdir(folder_path):
        # logger.debug(filename)
        if filename.endswith(".jpg") or filename.endswith(".jpeg"):  # 检查文件扩展名
            image_path = os.path.join(folder_path, filename)
            thread = threading.Thread(target=process_image, args=(image_path, face_detection_function, face_data, max_faces_per_frame))
            threads.append(thread)
            thread.start()

    # 等待所有线程完成
    for thread in threads:
        thread.join()
    return face_data


    
if __name__ == '__main__':
    # face_data = process_all_frames_in_folder("test_ffmpeg", F.从图片获取人脸数据)
    pass

